﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Xml.Linq;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;
using Microsoft.Phone.Tasks;
using System.Windows.Media.Imaging;
using Microsoft.Phone.Shell;

namespace PNut_Project_Lin
{

    public partial class MapPage : PhoneApplicationPage
    {


        public List<Pushpin> pinmap;
        public List<checkCar> points;

        checkCar xpoint;

        WebClient nearweb = new WebClient();

        GeoCoordinateWatcher watcher;
        public double laa;
        public double loo;

        Pushpin me = new Pushpin();


        public MapPage()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MapPage_Loaded);
        }

        void MapPage_Loaded(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
            //pinmap.Clear();
            StartLocationService(GeoPositionAccuracy.High);


            me.Content = "me";
            me.Template = null;
            ImageBrush ib = new ImageBrush();
            ib.ImageSource = new BitmapImage(new Uri("picture/bb copy.png", UriKind.Relative));
            me.Content = new Rectangle()
            {
                Fill = ib,
                Height = 56,
                Width = 56
            };


            try
            {

                Map_Ob.Children.Add(me);

            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }


            pinmap = new List<Pushpin>();
            points = new List<checkCar>();


            nearweb.DownloadStringCompleted += new DownloadStringCompletedEventHandler(nearweb_DownloadStringCompleted);


            nearweb.DownloadStringAsync(new Uri("http://www.mickku.com/Web2/get.xml"));

            ///  nearweb.DownloadStringAsync(new Uri("ลิ้งค์ที่เชื่อมต่อเพื่อดึงข้อมูลจาก webservice"));


        }

        void nearweb_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            XElement xmldoc = stripNS(XElement.Parse(e.Result));


            try
            {

                points = (from xml in xmldoc.Descendants("checkCar")
                          select new checkCar()
                          {
                              Name = xml.Element("Name").Value,

                              Detail = xml.Element("Detail").Value,

                              phone_call = xml.Element("phone_call").Value,

                              address = xml.Element("address").Value,

                              latitude = Convert.ToDouble(xml.Element("latitude").Value),

                              longtitude = Convert.ToDouble(xml.Element("longtitude").Value),

                              distance = calgps(laa, loo, Convert.ToDouble(xml.Element("latitude").Value), Convert.ToDouble(xml.Element("longtitude").Value))

                          }).ToList();

            }
            catch (Exception ex) { MessageBox.Show(ex.Message); }



            if (points.Count == 0)
            { MessageBox.Show("ไม่พบอู่ซ่อมรถ"); }
            else
            {
                Map_Ob.Children.Clear();


                ListBox.DataContext = points;

                for (int i = 0; i <= points.Count - 1; i++)
                {
                    try
                    {
                        Pushpin pin = new Pushpin();

                        pin.Location = new GeoCoordinate(points.ElementAt(i).latitude, points.ElementAt(i).longtitude);
                        pin.Content = points.ElementAt(i).Name;

                        var x = this.Resources["PushpinStyle"] as Style;

                        pin.Style = this.Resources["PushpinStyle"] as Style;



                        Uri imgUri = new Uri("Picture/PushpinCar.png", UriKind.RelativeOrAbsolute);
                        BitmapImage imgSourceR = new BitmapImage(imgUri);
                        ImageBrush imgBrush = new ImageBrush() { ImageSource = imgSourceR };

                        pin.Content = new Rectangle()
                        {
                            Fill = imgBrush,
                            Height = 36,
                            Width = 36
                        };

                        pin.Tag = points.ElementAt(i).Name;


                        pin.MouseLeftButtonUp += new MouseButtonEventHandler(pin_MouseLeftButtonUp);

                        pinmap.Add(pin);
                        Map_Ob.Children.Add(pinmap.Last());
                    }
                    catch { }
                }

                try
                {

                    Map_Ob.Children.Add(me);

                }
                catch (Exception ex) { MessageBox.Show(ex.Message); }


            }










        }

        void pin_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //throw new NotImplementedException();

            Pushpin pin = sender as Pushpin;


        eee: int i = 0;
            for (i = 0; i < points.Count; i++)
            {
                if (pin.Tag.ToString() == points.ElementAt(i).Name)
                {
                    break;
                }
            }

            if (i == -1)
            {
                MessageBox.Show("เกิดความผิดพลาด");
                goto eee;
            }


            xpoint = points.ElementAt(i);

            Name_lt.Text = xpoint.Name;
            Add_lt.Text = xpoint.address;
            Tel_lt.Text = xpoint.phone_call;
            Dis_lt.Text = xpoint.distance.ToString();


            st_CN.Visibility = System.Windows.Visibility.Visible;
            sumonTa.Visibility = System.Windows.Visibility.Visible;

            Map_Ob.Center = new GeoCoordinate(xpoint.latitude, xpoint.longtitude);
            Map_Ob.ZoomLevel = 15;

            sc_main.ScrollToVerticalOffset(sc_main.ScrollableHeight);

        }

        private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {



            xpoint = points.ElementAt(ListBox.SelectedIndex);
            Name_lt.Text = xpoint.Name;
            Add_lt.Text = xpoint.address;
            Tel_lt.Text = xpoint.phone_call;
            Dis_lt.Text = xpoint.distance.ToString();

            st_CN.Visibility = System.Windows.Visibility.Visible;
            sumonTa.Visibility = System.Windows.Visibility.Visible;

            Pano.DefaultItem = Pano.Items[0];
            Map_Ob.Center = new GeoCoordinate(xpoint.latitude, xpoint.longtitude);
            Map_Ob.ZoomLevel = 15;


            sc_main.ScrollToVerticalOffset(sc_main.ScrollableHeight);
        }



        /*
         Distance

This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is, the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points (ignoring any hills, of course!).

Haversine
formula:	 a = sin²(Δφ/2) + cos(φ1).cos(φ2).sin²(Δλ/2)
c = 2.atan2(√a, √(1−a))
d = R.c
where	φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km)
 	note that angles need to be in radians to pass to trig functions!
JavaScript:	
var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;
         */
        public double calgps(double la, double lo, double la2, double lo2)
        {

            double lat = la2 - la;
            double lon = lo2 - lo;

            double a = Math.Pow(Math.Sin(lat / 2), 2) + Math.Cos(la) * Math.Cos(la2) * Math.Pow(Math.Sin(lon / 2), 2);

            double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

            double d = 6371 * c * 1.85 * 10;

            double dis = d / 1000;

            string sdis = dis.ToString();

            sdis = sdis.Substring(0, 5);


            return Convert.ToDouble(sdis);
        }


        static XElement stripNS(XElement root)
        {
            XElement res = new XElement(
                root.Name.LocalName,
                root.HasElements ?
                    root.Elements().Select(el => stripNS(el)) :
                    (object)root.Value
            );

            res.ReplaceAttributes(
                root.Attributes().Where(attr => (!attr.IsNamespaceDeclaration)));

            return res;
        }



        ////////////////////////////////gps//////////////////////////////

        private void StartLocationService(GeoPositionAccuracy accuracy)
        {
            // Reinitialize the GeoCoordinateWatcher
            watcher = new GeoCoordinateWatcher(accuracy);
            watcher.MovementThreshold = 20;

            // Add event handlers for StatusChanged and PositionChanged events
            watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);

            // Start data acquisition
            watcher.Start();

        }


        void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MyStatusChanged(e));

        }

        void MyStatusChanged(GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:

                    break;
                case GeoPositionStatus.Initializing:

                    break;
                case GeoPositionStatus.NoData:

                    break;
                case GeoPositionStatus.Ready:

                    break;

            }
        }


        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => MyPositionChanged(e));
        }


        void MyPositionChanged(GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            // Update the TextBlocks to show the current location

            laa = e.Position.Location.Latitude;
            loo = e.Position.Location.Longitude;

            Map_Ob.Center = e.Position.Location;

            me.Location = e.Position.Location;


        }

        private void Map_Ob_Hold(object sender, GestureEventArgs e)
        {
            if (ApplicationBar.IsVisible == true)
            {
                ApplicationBar.IsVisible = false;
            }
            else { ApplicationBar.IsVisible = true; }


        }

        private void Call_im_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            PhoneCallTask task = new PhoneCallTask();
            task.PhoneNumber = xpoint.phone_call;
            task.DisplayName = xpoint.Name;
            task.Show();
        }

        private void Navi_im_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            BingMapsDirectionsTask directionsTask = new BingMapsDirectionsTask();

            if (String.IsNullOrEmpty(Name_lt.Text))
            {
                MessageBox.Show("กรุณาเลือกอู่ที่ต้องการนำทาง");
                return;
            }

            directionsTask.Start = new LabeledMapLocation("Me", new GeoCoordinate(laa, loo));
            directionsTask.End = new LabeledMapLocation(xpoint.Name, new GeoCoordinate(xpoint.latitude, xpoint.longtitude));

            directionsTask.Show();

        }

        private void mode_Click(object sender, EventArgs e)
        {
            if (Map_Ob.Mode is AerialMode)
            {
                Map_Ob.Mode = new RoadMode();
            }
            else
            {
                Map_Ob.Mode = new AerialMode(true);
            }
        }

        private void me_a_Click(object sender, EventArgs e)
        {
            Map_Ob.Center = me.Location;
        }







    }
}